package io.aircraft.modules.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.aircraft.common.constant.BusinessTypeConstants;
import io.aircraft.common.constant.SerialNumConstants;
import io.aircraft.common.page.PageData;
import io.aircraft.common.service.impl.CrudServiceImpl;
import io.aircraft.common.utils.ConvertUtils;
import io.aircraft.common.utils.ProcResult;
import io.aircraft.common.utils.Result;
import io.aircraft.modules.sys.dto.SysUserDTO;
import io.aircraft.modules.sys.service.SysUserService;
import io.aircraft.modules.wms.dao.OrderDao;
import io.aircraft.modules.wms.dto.OrderDTO;
import io.aircraft.modules.wms.dto.OrderDetailDTO;
import io.aircraft.modules.wms.entity.*;
import io.aircraft.modules.wms.entity.stored.*;
import io.aircraft.modules.wms.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 出库主单
 *
 * @author Cycle gengruyi01@163.com
 * @since 1.0.0 2022-11-16
 */
@Service
public class OrderServiceImpl extends CrudServiceImpl<OrderDao, OrderEntity, OrderDTO> implements OrderService {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private SerialNumberService serialNumberService;
    @Autowired
    private StoredProcService storedProcService;
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public PageData<OrderDTO> page(Map<String, Object> params) {
        //查询出库订单
        IPage<OrderEntity> page = baseDao.selectPage(
                getPage(params, "order_id", false),
                getWrapper(params)
        );
        //查询所有主单对应的明细信息
        List<OrderDetailDTO> detailList = orderDetailService.getAllDetail();
        //获取[sys_user]的信息
        List<SysUserDTO> userList = sysUserService.getList();
        //将主单与明细项进行绑定
        page.getRecords().forEach(entity -> {
            entity.setCreatorName(sysUserService.getUsernameById(entity.getCreator(), userList));
            entity.setUpdaterName(sysUserService.getUsernameById(entity.getUpdater(), userList));
            entity.setOrderDetailList(orderDetailService.getDetailByOrderId(entity.getOrderId(), detailList));
        });
        return getPageData(page, OrderDTO.class);
    }

    @Override
    public QueryWrapper<OrderEntity> getWrapper(Map<String, Object> params) {
        String orderNo = (String) params.get("orderNo");
        QueryWrapper<OrderEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(orderNo), "order_no", orderNo);

        return wrapper;
    }

    /**
     * 出库主单的新增逻辑
     *
     * @param dto 主单实体dto
     */
    @Transactional
    public Long saveOrder(OrderDTO dto) {
        //1.获取需求数量
        BigDecimal amount = dto.getAmount();
        //2.获取单据编号
        String orderNo = serialNumberService.getSerialNumberByCode(SerialNumConstants.ORDER_MODULE_CODE);
        //3.填充单据信息
        dto.setOrderNo(orderNo);
        dto.setOrderType(BusinessTypeConstants.WO_OT_FP);
        //4.将数据转换为对象实体
        OrderEntity entity = ConvertUtils.sourceToTarget(dto, OrderEntity.class);
        //5.将主单写入数据库
        insert(entity);
        //6.根据amount生成明细信息
        List<OrderDetailDTO> dtoList = new ArrayList<>();
        OrderDetailDTO detailDTO = new OrderDetailDTO();
        detailDTO.setOrderId(entity.getOrderId());
        detailDTO.setSpuNo(entity.getSpuNo());
        detailDTO.setLotNo(entity.getLotNo());
        detailDTO.setPlanQnty(BigDecimal.valueOf(1L));
        for (int i = 0; i < amount.intValue(); i++) {
            dtoList.add(detailDTO);
        }
        orderDetailService.batchSave(dtoList);
        return entity.getOrderId();
    }

    @Override
    public OrderDTO getListByStation(String stationNo) {
        OrderEntity entity = baseDao.selectByStation(stationNo);
        if (entity == null) {
            return null;
        }
        return ConvertUtils.sourceToTarget(entity, OrderDTO.class);
    }

    @Override
    public ProcResult releaseTask(OrderDTO dto) {
        String errMsg = "";
        //0.确认3台堆垛机是否可用
        final List<String> dvcList = getDvcList();
        System.out.println(dvcList);
        if (null == dvcList || dvcList.size() == 0) {
            return new ProcResult().result("500", "当前无可用堆垛机!请检查设备情况!");
        }
        //1.校验可用设备上是否存在充足的库存
        ProcStockCheckEntity params = new ProcStockCheckEntity();
        params.setSpuNo(dto.getSpuNo());
        params.setLotNo(dto.getLotNo());
        params.setTcList(String.join(",", dvcList));
        params.setReqQnty(dto.getAmount());
        final ProcResult procResult = storedProcService.stockCheck(params);
        //库存不足则返回
        if (!procResult.getCode().equals("0")) {
            return procResult;
        }
        //2.单据生成并保存
        Long orderId = saveOrder(dto);
        if (orderId != null) {
            return orderAllot(orderId);
        }
        return new ProcResult().result("500", "生成出库单据异常!");
    }

    @Override
    public ProcResult orderCancel(Long id) {
        ProcOrderCancelEntity parameters = new ProcOrderCancelEntity();
        parameters.setOrderId(id);
        return storedProcService.orderCancelById(parameters);
    }

    @Override
    public ProcResult orderAllot(Long id) {
        ProcOrderAllotEntity parameters = new ProcOrderAllotEntity();
        parameters.setOrderId(id);
        return storedProcService.autoAllotById(parameters);
    }

    @Override
    public ProcResult orderRefund(Long id) {
        ProcOrderRefundEntity parameters = new ProcOrderRefundEntity();
        parameters.setOrderId(id);
        return storedProcService.refundById(parameters);
    }

    @Override
    public ProcResult orderAudi(Long id) {
        //4.调用[出库执行]逻辑进行处理
        ProcOrderAudiEntity parameters = new ProcOrderAudiEntity();
        parameters.setOrderId(id);
        return storedProcService.audiById(parameters);
    }

    /**
     * 出库单据挂起
     */
    @Override
    public ProcResult orderHangUp(Long id) {
        final OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOrderId(id);
        orderEntity.setOrderSt(2);
        final int num = baseDao.updateById(orderEntity);
        if (num == 0) {
            return new ProcResult().result("500", "单据挂起异常!");
        }
        return new ProcResult();
    }

    private List<String> getDvcList() {
        //远程访问wcs并询问设备的可用情况
        String url = "http://localhost:8088/wcs-admin/api/wcs-dvc/state";
        try {
            final ResponseEntity<Result> response = restTemplate.getForEntity(url, Result.class);
            final List<Map> data = (List<Map>) response.getBody().getData();
            return data.stream().map(map -> (String) map.get("dvcNo")).filter(Objects::nonNull)
                    .collect(Collectors.toList());
        } catch (Exception ex) {
            return null;
        }
    }
}